<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:pkg="http://expath.org/ns/pkg"
                xmlns:doc="http://www.oxygenxml.com/ns/doc/xsl"
                xmlns:gdoc="http://fgeorges.org/ns/google/docs"
                xmlns:gdata="http://fgeorges.org/ns/google/data"
                xmlns:atom="http://www.w3.org/2005/Atom"
                xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
                xmlns:http="http://expath.org/ns/http-client"
                xmlns:impl="urn:X-FGeorges:xslt:google:gdocs:impl"
                xmlns:gd="http://schemas.google.com/g/2005"
                exclude-result-prefixes="#all"
                version="2.0">

   <xsl:import href="http://expath.org/ns/http-client.xsl"/>
   <xsl:import href="gdata.xsl"/>

   <pkg:import-uri>http://fgeorges.org/ns/google/gdocs.xsl</pkg:import-uri>


   <!-- ...........................................................................................
      Table of contents.
      
      - global parameters and variables
      - the document service
      - the feeds ctors
      - query parameters
      - high-level routines (TODO: to be completed)
      - OLD code (TODO: to adapt or remove)
   -->

   <doc:doc scope="stylesheet">
      <doc:desc>
         <doc:p><doc:b>Created on:</doc:b> Feb 1, 2009</doc:p>
         <doc:p><doc:b>Author:</doc:b> Florent Georges</doc:p>
         <doc:p>XSLT module providing Google Documents API 3.0.</doc:p>
         <doc:p>
            Copyright (c) statement at the end of the file.
         </doc:p>
         <doc:p>
            See Google Documents API documentation at
            <doc:a href="http://code.google.com/apis/documents/docs/"/>.
         </doc:p>
      </doc:desc>
   </doc:doc>


   <!-- ...........................................................................................
      Global parameters and variables.
   -->

   <doc:doc>
      <doc:desc>MIME type for Open Document Text files.</doc:desc>
   </doc:doc>
   <xsl:variable name="gdoc:odt-mime-type" select="'application/vnd.oasis.opendocument.text'"/>

   <doc:doc>
      <doc:desc>The name of the Google Documents service.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:docs-service-name" as="xs:string" select="'writely'"/>

   <doc:doc>
      <doc:desc>The URI of the feed for all documents of the service's logged in user.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:private-docs-feed" as="xs:string" select="
       'https://docs.google.com/feeds/default/private/full'"/>


   <!-- ...........................................................................................
      The document service.
      
      - gdoc:make-login-doc-service($token)
      - gdoc:make-login-doc-service($user, $pwd)
      - gdoc:make-authsub-doc-service($token)
   -->

   <doc:doc>
      <doc:desc>Make a new GData service element, for the document
         service, with Client Login authentication.</doc:desc>
      <doc:param name="token">
         The authentication token.
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:make-login-doc-service" as="element(gdata:service)">
      <xsl:param name="token" as="xs:string"/>
      <xsl:sequence select="gdata:make-login-service($impl:docs-service-name, $token, '3.0')"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Make a new GData service element, for the document
         service, with Client Login authentication.</doc:desc>
      <doc:param name="user">
         <para>The user name, as an email address.</para>
      </doc:param>
      <doc:param name="pwd">
         <para>The password.</para>
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:make-login-doc-service" as="element(gdata:service)">
      <xsl:param name="email" as="xs:string"/>
      <xsl:param name="pwd"   as="xs:string"/>
      <xsl:variable name="token" select="gdata:authenticate-login($impl:docs-service-name, $email, $pwd)"/>
      <xsl:sequence select="gdoc:make-login-doc-service($token)"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Make a new GData service element, for the document
         service, with AuthSub authentication.</doc:desc>
      <doc:param name="token">
         The authentication token.
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:make-authsub-doc-service" as="element(gdata:service)">
      <xsl:param name="token" as="xs:string"/>
      <xsl:sequence select="gdata:make-authsub-service($impl:docs-service-name, $token, '3.0')"/>
   </xsl:function>


   <!-- ...........................................................................................
      The feeds ctors.
      
      - gdoc:feed-documents-list()
      - gdoc:feed-documents-list($resource-id)
      - gdoc:feed-documents-list($resource-id, $visibility, $projection)
      - gdoc:feed-documents-list($resource-id, $visibility, $projection, $query)
      - gdoc:feed-root-folder()
      - gdoc:feed-folders($resource-id)
      - gdoc:feed-fodlers($resource-id, $visibility, $projection)
      - gdoc:feed-folders($resource-id, $visibility, $projection, $query)
      - gdoc:feed-acl($resource-id)
      - gdoc:feed-acl($resource-id, $visibility, $projection)
      - gdoc:feed-acl($resource-id, $visibility, $projection, $query)
      - gdoc:feed-media($resource-id)
      - gdoc:feed-media($resource-id, $query)
      - gdoc:feed-revisions($resource-id)
      - gdoc:feed-revisions($resource-id, $revision-id, $visibility, $projection)
      - gdoc:feed-revisions($resource-id, $revision-id, $visibility, $projection, $query)
      - gdoc:feed-resumable-upload()
      - gdoc:feed-resumable-upload($visibility, $projection)
      - gdoc:feed-resumable-upload($visibility, $projection, $query)
      - gdoc:feed-documents-export()
      - gdoc:feed-presentations-export()
      - gdoc:feed-spreadsheets-export()
   -->

   <xsl:function name="gdoc:feed-documents-list" as="element(gdoc:feed)">
      <xsl:sequence select="gdoc:feed-documents-list((), (), ())"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-documents-list" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:sequence select="gdoc:feed-documents-list($resource-id, (), ())"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-documents-list" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string?"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:variable name="vis" as="xs:string" select="( $visibility, 'private' )[1]"/>
      <xsl:variable name="pro" as="xs:string" select="( $projection, 'full' )[1]"/>
      <gdoc:feed>
         <xsl:text>https://docs.google.com/feeds/default/</xsl:text>
         <xsl:value-of select="$vis"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$pro"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$resource-id"/> <!-- optional -->
      </gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-documents-list" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string?"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:param name="params"      as="element()*"/>
      <xsl:variable name="res" as="xs:string?" select="( $resource-id, $params[self::gdoc:resource-id] )[1]"/>
      <xsl:variable name="vis" as="xs:string?" select="( $visibility, $params[self::gdoc:visibility] )[1]"/>
      <xsl:variable name="pro" as="xs:string?" select="( $projection, $params[self::gdoc:projection] )[1]"/>
      <xsl:sequence select="gdoc:feed-documents-list($res, $vis, $pro)"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-root-folder" as="element(gdoc:feed)">
      <xsl:sequence select="gdoc:feed-folders('folder%3Aroot')"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-folders" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:sequence select="gdoc:feed-folders($resource-id, (), ())"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-folders" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:variable name="vis" as="xs:string" select="( $visibility, 'private' )[1]"/>
      <xsl:variable name="pro" as="xs:string" select="( $projection, 'full' )[1]"/>
      <gdoc:feed>
         <xsl:text>https://docs.google.com/feeds/default/</xsl:text>
         <xsl:value-of select="$vis"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$pro"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$resource-id"/>
         <xsl:text>/contents</xsl:text>
      </gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-folders" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string?"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:param name="params"      as="element()*"/>
      <xsl:variable name="res" as="xs:string?" select="( $resource-id, $params[self::gdoc:resource-id] )[1]"/>
      <xsl:variable name="vis" as="xs:string?" select="( $visibility, $params[self::gdoc:visibility] )[1]"/>
      <xsl:variable name="pro" as="xs:string?" select="( $projection, $params[self::gdoc:projection] )[1]"/>
      <xsl:sequence select="gdoc:feed-folders($res, $vis, $pro)"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-acl" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:sequence select="gdoc:feed-acl($resource-id, (), ())"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-acl" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:variable name="vis" as="xs:string" select="( $visibility, 'private' )[1]"/>
      <xsl:variable name="pro" as="xs:string" select="( $projection, 'full' )[1]"/>
      <gdoc:feed>
         <xsl:text>https://docs.google.com/feeds/default/</xsl:text>
         <xsl:value-of select="$vis"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$pro"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$resource-id"/>
         <xsl:text>/acl</xsl:text>
      </gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-acl" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string?"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:param name="params"      as="element()*"/>
      <xsl:variable name="res" as="xs:string?" select="( $resource-id, $params[self::gdoc:resource-id] )[1]"/>
      <xsl:variable name="vis" as="xs:string?" select="( $visibility, $params[self::gdoc:visibility] )[1]"/>
      <xsl:variable name="pro" as="xs:string?" select="( $projection, $params[self::gdoc:projection] )[1]"/>
      <xsl:sequence select="gdoc:feed-acl($res, $vis, $pro)"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-media" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <gdoc:feed>
         <xsl:text>https://docs.google.com/feeds/default/media/</xsl:text>
         <xsl:value-of select="$resource-id"/>
      </gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-media" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string?"/>
      <xsl:param name="params"      as="element()*"/>
      <xsl:variable name="res" as="xs:string?" select="( $resource-id, $params[self::gdoc:resource-id] )[1]"/>
      <xsl:sequence select="gdoc:feed-media($res)"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-revisions" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:sequence select="gdoc:feed-revisions($resource-id, (), (), ())"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-revisions" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string"/>
      <xsl:param name="revision-id" as="xs:string?"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:variable name="vis" as="xs:string" select="( $visibility, 'private' )[1]"/>
      <xsl:variable name="pro" as="xs:string" select="( $projection, 'full' )[1]"/>
      <gdoc:feed>
         <xsl:text>https://docs.google.com/feeds/default/</xsl:text>
         <xsl:value-of select="$vis"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$pro"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$resource-id"/>
         <xsl:text>/revisions/</xsl:text>
         <xsl:value-of select="$revision-id"/> <!-- optional -->
      </gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-revisions" as="element(gdoc:feed)">
      <xsl:param name="resource-id" as="xs:string?"/>
      <xsl:param name="revision-id" as="xs:string?"/>
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:param name="params"      as="element()*"/>
      <xsl:variable name="res" as="xs:string?" select="( $resource-id, $params[self::gdoc:resource-id] )[1]"/>
      <xsl:variable name="rev" as="xs:string?" select="( $revision-id, $params[self::gdoc:revision-id] )[1]"/>
      <xsl:variable name="vis" as="xs:string?" select="( $visibility, $params[self::gdoc:visibility] )[1]"/>
      <xsl:variable name="pro" as="xs:string?" select="( $projection, $params[self::gdoc:projection] )[1]"/>
      <xsl:sequence select="gdoc:feed-revisions($res, $rev, $vis, $pro)"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-resumable-upload" as="element(gdoc:feed)">
      <xsl:sequence select="gdoc:feed-resumable-upload((), ())"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-resumable-upload" as="element(gdoc:feed)">
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:variable name="vis" as="xs:string" select="( $visibility, 'private' )[1]"/>
      <xsl:variable name="pro" as="xs:string" select="( $projection, 'full' )[1]"/>
      <gdoc:feed>
         <xsl:text>https://docs.google.com/feeds/upload/create-session/default/</xsl:text>
         <xsl:value-of select="$vis"/>
         <xsl:text>/</xsl:text>
         <xsl:value-of select="$pro"/>
      </gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-resumable-upload" as="element(gdoc:feed)">
      <xsl:param name="visibility"  as="xs:string?"/>
      <xsl:param name="projection"  as="xs:string?"/>
      <xsl:param name="params"      as="element()*"/>
      <xsl:variable name="vis" as="xs:string?" select="( $visibility, $params[self::gdoc:visibility] )[1]"/>
      <xsl:variable name="pro" as="xs:string?" select="( $projection, $params[self::gdoc:projection] )[1]"/>
      <xsl:sequence select="gdoc:feed-resumable-upload($vis, $pro)"/>
   </xsl:function>

   <xsl:function name="gdoc:feed-documents-export" as="element(gdoc:feed)">
      <gdoc:feed>https://docs.google.com/feeds/download/documents/Export</gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-presentations-export" as="element(gdoc:feed)">
      <gdoc:feed>https://docs.google.com/feeds/download/presentations/Export</gdoc:feed>
   </xsl:function>

   <xsl:function name="gdoc:feed-spreadsheets-export" as="element(gdoc:feed)">
      <gdoc:feed>https://spreadsheets.google.com/feeds/download/spreadsheets/Export</gdoc:feed>
   </xsl:function>


   <!-- ...........................................................................................
      Query parameters.
      
      - gdoc:param-title($value)
      - gdoc:param-title-exact($value)
      - gdoc:param-opened-min($value)
      - gdoc:param-opened-max($value)
      - gdoc:param-edited-min($value)
      - gdoc:param-edited-max($value)
      - gdoc:param-owner($value)
      - gdoc:param-writer($value)
      - gdoc:param-reader($value)
      - gdoc:param-showfolders($value)
      - gdoc:param-showdeleted($value)
      - gdoc:param-ocr($value)
      - gdoc:param-targetLanguage($value)
      - gdoc:param-sourceLanguage($value)
      - gdoc:param-delete($value)
      - gdoc:param-convert($value)
      - gdoc:param-docID($value)
      - gdoc:param-exportFormat($value)
      - gdoc:param-key($value)
      - gdoc:param-gid($value)
      - gdoc:category-starred()
      - gdoc:category-trashed()
      - gdoc:category-hidden()
      - gdoc:category-viewed()
      - gdoc:category-mine()
      - gdoc:category-private()
      - gdoc:category-shared-with-domain()
      - gdoc:type-document()
      - gdoc:type-folder()
      - gdoc:type-pdf()
      - gdoc:type-presentation()
      - gdoc:type-spreadsheet()
      - gdoc:type-form()
      
      See http://code.google.com/apis/documents/docs/3.0/reference.html.
   -->

   <doc:doc>
      <doc:desc>Return a raw query parameter 'title'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-title" as="element(gdoc:title)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:title>
         <xsl:value-of select="$value"/>
      </gdoc:title>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'title-exact'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-title-exact" as="element(gdoc:title-exact)">
      <xsl:param name="value" as="xs:boolean"/>
      <gdoc:title-exact>
         <xsl:value-of select="$value"/>
      </gdoc:title-exact>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'opened-min'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-opened-min" as="element(gdoc:opened-min)">
      <xsl:param name="value" as="xs:dateTime"/>
      <gdoc:opened-min>
         <xsl:value-of select="$value"/>
      </gdoc:opened-min>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'opened-max'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-opened-max" as="element(gdoc:opened-max)">
      <xsl:param name="value" as="xs:dateTime"/>
      <gdoc:opened-max>
         <xsl:value-of select="$value"/>
      </gdoc:opened-max>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'edited-min'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-edited-min" as="element(gdoc:edited-min)">
      <xsl:param name="value" as="xs:dateTime"/>
      <gdoc:edited-min>
         <xsl:value-of select="$value"/>
      </gdoc:edited-min>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'edited-max'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-edited-max" as="element(gdoc:edited-max)">
      <xsl:param name="value" as="xs:dateTime"/>
      <gdoc:edited-max>
         <xsl:value-of select="$value"/>
      </gdoc:edited-max>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'owner'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-owner" as="element(gdoc:owner)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:owner>
         <xsl:value-of select="$value"/>
      </gdoc:owner>
   </xsl:function>

   <!--
       TODO: Can be "a single email address or a comma separated list
       of email addresses".  So it would be interesting to accept a
       sequence of strings, and concatenate them...
   -->
   <doc:doc>
      <doc:desc>Return a raw query parameter 'writer'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-writer" as="element(gdoc:writer)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:writer>
         <xsl:value-of select="$value"/>
      </gdoc:writer>
   </xsl:function>

   <!--
       TODO: Can be "a single email address or a comma separated list
       of email addresses".  So it would be interesting to accept a
       sequence of strings, and concatenate them...
   -->
   <doc:doc>
      <doc:desc>Return a raw query parameter 'reader'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-reader" as="element(gdoc:reader)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:reader>
         <xsl:value-of select="$value"/>
      </gdoc:reader>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'showfolders'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-showfolders" as="element(gdoc:showfolders)">
      <xsl:param name="value" as="xs:boolean"/>
      <gdoc:showfolders>
         <xsl:value-of select="$value"/>
      </gdoc:showfolders>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'showdeleted'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-showdeleted" as="element(gdoc:showdeleted)">
      <xsl:param name="value" as="xs:boolean"/>
      <gdoc:showdeleted>
         <xsl:value-of select="$value"/>
      </gdoc:showdeleted>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'ocr'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-ocr" as="element(gdoc:ocr)">
      <xsl:param name="value" as="xs:dateTime"/>
      <gdoc:ocr>
         <xsl:value-of select="$value"/>
      </gdoc:ocr>
   </xsl:function>

   <!--
       TODO: There is a list of possible values: "See Document
       Translation[1] in the Protocol Guide for a table of possible
       values".
       [1]http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html#DocumentTranslation
   -->
   <doc:doc>
      <doc:desc>Return a raw query parameter 'targetLanguage'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-targetLanguage" as="element(gdoc:targetLanguage)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:targetLanguage>
         <xsl:value-of select="$value"/>
      </gdoc:targetLanguage>
   </xsl:function>

   <!--
       TODO: There is a list of possible values: "See Document
       Translation[1] in the Protocol Guide for a table of possible
       values".
       [1]http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html#DocumentTranslation
   -->
   <doc:doc>
      <doc:desc>Return a raw query parameter 'sourceLanguage'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-sourceLanguage" as="element(gdoc:sourceLanguage)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:sourceLanguage>
         <xsl:value-of select="$value"/>
      </gdoc:sourceLanguage>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'delete'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-delete" as="element(gdoc:delete)">
      <xsl:param name="value" as="xs:boolean"/>
      <gdoc:delete>
         <xsl:value-of select="$value"/>
      </gdoc:delete>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'convert'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-convert" as="element(gdoc:convert)">
      <xsl:param name="value" as="xs:boolean"/>
      <gdoc:convert>
         <xsl:value-of select="$value"/>
      </gdoc:convert>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'docID'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-docID" as="element(gdoc:docID)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:docID>
         <xsl:value-of select="$value"/>
      </gdoc:docID>
   </xsl:function>

   <doc:doc>
      <doc:desc>Possible values for the query parameter 'exportFormat'.</doc:desc>
   </doc:doc>
   <xsl:variable name="gdoc:param-exportFormat-enum" select="
       'csv',
       'doc',
       'html',
       'ods',
       'odt',
       'pdf',
       'png',
       'ppt',
       'rtf',
       'swf',
       'tsv',
       'txt',
       'xls',
       'zip'"/>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'exportFormat'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-exportFormat" as="element(gdoc:exportFormat)">
      <xsl:param name="value" as="xs:string"/>
      <xsl:if test="not($value = $gdoc:param-exportFormat-enum)">
         <xsl:sequence select="gdata:error('GDATA012', $value)"/>
      </xsl:if>
      <gdoc:exportFormat>
         <xsl:value-of select="$value"/>
      </gdoc:exportFormat>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'key'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-key" as="element(gdoc:key)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:key>
         <xsl:value-of select="$value"/>
      </gdoc:key>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query parameter 'gid'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:param-gid" as="element(gdoc:gid)">
      <xsl:param name="value" as="xs:string"/>
      <gdoc:gid>
         <xsl:value-of select="$value"/>
      </gdoc:gid>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'starred'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-starred" as="element(gdoc:category)">
      <gdoc:category>starred</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'trashed'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-trashed" as="element(gdoc:category)">
      <gdoc:category>trashed</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'hidden'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-hidden" as="element(gdoc:category)">
      <gdoc:category>hidden</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'viewed'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-viewed" as="element(gdoc:category)">
      <gdoc:category>viewed</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'mine'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-mine" as="element(gdoc:category)">
      <gdoc:category>mine</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'private'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-private" as="element(gdoc:category)">
      <gdoc:category>private</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category parameter for 'shared-with-domain'.</doc:desc>
   </doc:doc>
   <xsl:function name="gdoc:category-shared-with-domain" as="element(gdoc:category)">
      <gdoc:category>shared-with-domain</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category for type 'document'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:type-document" as="element(gdoc:category)">
      <gdoc:category>document</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category for type 'folder'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:type-folder" as="element(gdoc:category)">
      <gdoc:category>folder</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category for type 'pdf'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:type-pdf" as="element(gdoc:category)">
      <gdoc:category>pdf</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category for type 'presentation'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:type-presentation" as="element(gdoc:category)">
      <gdoc:category>presentation</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category for type 'spreadsheet'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:type-spreadsheet" as="element(gdoc:category)">
      <gdoc:category>spreadsheet</gdoc:category>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return a raw query category for type 'form'.</doc:desc>
      <doc:param name="value">The value to use for that parameter.</doc:param>
   </doc:doc>
   <xsl:function name="gdoc:type-form" as="element(gdoc:category)">
      <gdoc:category>form</gdoc:category>
   </xsl:function>


   <!-- ...........................................................................................
      High-level routines.
      
      - gdoc:get-root-folder($service)
      - gdoc:get-top-level-folders($service)
      - gdoc:get-subfolders($service, $dir)
      - gdoc:resource-id($entry)
   -->

   <!--
       TODO: Does not seem to work (does the root folder have a
       corresponding Atom entry?).  See the issue #1892
       <http://code.google.com/p/gdata-issues/issues/detail?id=1892>.
   -->
   <xsl:function name="gdoc:get-root-folder" as="element(atom:entry)">
      <xsl:param name="service" as="element(gdata:service)"/>
      <xsl:sequence select="
          gdata:query(
            $service,
            gdoc:feed-documents-list('folder%3Aroot'),
            ())"/>
   </xsl:function>

   <xsl:function name="gdoc:get-top-level-folders" as="element(atom:feed)+">
      <xsl:param name="service" as="element(gdata:service)"/>
      <xsl:variable name="query" select="
          gdoc:feed-folders('folder%3Aroot'),
          gdoc:type-folder()"/>
      <xsl:sequence select="gdata:query-all($service, $query, 1)"/>
   </xsl:function>

   <xsl:function name="gdoc:get-subfolders" as="element(atom:feed)+">
      <xsl:param name="service" as="element(gdata:service)"/>
      <xsl:param name="dir"     as="element(atom:entry)"/>
      <xsl:variable name="query" select="
          gdoc:feed-folders(gdoc:resource-id($dir)),
          gdoc:type-folder()"/>
      <xsl:sequence select="gdata:query-all($service, $query, 1)"/>
   </xsl:function>

   <xsl:function name="gdoc:resource-id" as="xs:string">
      <xsl:param name="entry" as="element(atom:entry)"/>
      <xsl:sequence select="$entry/gd:resourceId"/>
   </xsl:function>


   <!-- ...........................................................................................
      OLD code:
      
      - gdoc:get-folders($service)
      - gdoc:get-folders($service, $params)
      - gdoc:upload-file($service, $href, $content-type, $folder)
      - gdoc:folder-uri($folder)
      
      TODO: Everything after here is old code, still to be adapted to
      the new query system (or be removed)...
   -->

   <!--doc:function>
      <para>Get the list of all folders.</para>
      <doc:param name="service">
         <para>The document service.</para>
      </doc:param>
   </doc:function>
   <xsl:function name="gdoc:get-folders" as="element(atom:feed)*">
      <!- - the service element - ->
      <xsl:param name="service" as="element(gdata:service)"/>
      <xsl:sequence select="gdoc:get-folders($service, ())"/>
   </xsl:function-->

   <!--doc:function>
      <para>Get the list of all folders.</para>
      <doc:param name="service">
         <para>The document service.</para>
      </doc:param>
      <doc:param name="params">
         <para>The parameters to use in the query.</para>
      </doc:param>
   </doc:function>
   <xsl:function name="gdoc:get-top-level-folders" as="element(atom:feed)*">
      <!- - the service element - ->
      <xsl:param name="service" as="element(gdata:service)"/>
      <!- - query parameters - ->
      <xsl:param name="params"  as="element(gdata:param)*"/>
      <xsl:variable name="all-params" as="element(gdata:param)+">
         <gdata:param name="category"    value="folder"/>
         <gdata:param name="showfolders" value="true"/>
         <xsl:sequence select="$params"/>
      </xsl:variable>
      <xsl:variable name="uri" select="
          concat($impl:private-docs-feed, '/folder%3Aroot/contents')"/>
      <xsl:sequence select="
          gdata:get-all-feeds($service, $uri, $all-params)"/>
   </xsl:function-->

   <!--doc:function>
      <para>Get the list of all folders.</para>
      <doc:param name="service">
         <para>The document service.</para>
      </doc:param>
      <doc:param name="params">
         <para>The parameters to use in the query.</para>
      </doc:param>
   </doc:function-->
   <xsl:function name="gdoc:get-folder-contents" as="element(atom:feed)*">
      <!-- the service element -->
      <xsl:param name="service" as="element(gdata:service)"/>
      <!-- the folder ID -->
      <xsl:param name="folder"  as="xs:string"/>
      <xsl:variable name="uri" select="
          concat($impl:private-docs-feed, '/folder%3A', $folder, '/contents')"/>
      <xsl:sequence select="gdata:get-all-feeds($service, $uri)"/>
   </xsl:function>

   <!--doc:function>
      <para>Get the list of all folders.</para>
      <doc:param name="service">
         <para>The document service.</para>
      </doc:param>
      <doc:param name="params">
         <para>The parameters to use in the query.</para>
      </doc:param>
   </doc:function-->
   <!-- TODO: ... -->
   <!--xsl:function name="gdoc:get-all-folders-and-docs" as="element(atom:feed)*">
      <!- - the service element - ->
      <xsl:param name="service" as="element(gdata:service)"/>
      <xsl:variable name="uri" select="
          concat($impl:private-docs-feed, '/folder%3A', $folder, '/contents')"/>
      <xsl:sequence select="gdata:get-all-feeds($service, $uri)"/>
   </xsl:function-->

   <xsl:function name="gdoc:upload-file" as="element(atom:entry)">
      <xsl:param name="service"      as="element(gdata:service)"/>
      <xsl:param name="href"         as="xs:string"/>
      <xsl:param name="content-type" as="xs:string"/>
      <xsl:sequence select="gdoc:upload-file($service, $href, $content-type, ())"/>
   </xsl:function>

   <xsl:function name="gdoc:upload-file" as="element(atom:entry)">
      <xsl:param name="service"      as="element(gdata:service)"/>
      <xsl:param name="href"         as="xs:string"/>
      <xsl:param name="content-type" as="xs:string"/>
      <xsl:param name="title"        as="xs:string?"/>
      <xsl:sequence select="gdoc:upload-file($service, $href, $content-type, $title, ())"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Upload a file to the service.</doc:desc>
      <doc:param name="service">
         The document service.
      </doc:param>
      <doc:param name="href">
         The URI of the file to upload.
      </doc:param>
      <doc:param name="content-type">
         The MIME media type of the file to upload.
      </doc:param>
      <doc:param name="folder">
         <doc:p>The folder to upload the file to (the folder ID.)  Can
           be the empty sequence to not upload to any particular
           folder.</doc:p>
         <doc:p>TODO: We should be able to use either an ID
           or an entry, for the folder!</doc:p>
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:upload-file" as="element(atom:entry)">
      <xsl:param name="service"      as="element(gdata:service)"/>
      <xsl:param name="href"         as="xs:string"/>
      <xsl:param name="content-type" as="xs:string"/>
      <xsl:param name="title"        as="xs:string?"/>
      <xsl:param name="folder"       as="xs:string?"/>
      <xsl:variable name="uri" as="xs:string" select="
          if ( exists($folder) ) then
            impl:folder-uri($folder)
          else
            $impl:private-docs-feed"/>
      <!-- the HTTP request element -->
      <xsl:variable name="req" as="element(http:request)">
         <http:request method="post" href="{ $uri }">
            <http:header name="GData-Version" value="2.0"/>
            <http:header name="Authorization"
                         value="GoogleLogin auth={ $service/gdata:auth-token }"/>
            <xsl:variable name="body" as="element()+">
               <http:header name="Slug" value="{ impl:basename($href) }"/>
               <http:body content-type="{ $content-type }" href="{ $href }"/>
            </xsl:variable>
            <xsl:choose>
               <xsl:when test="exists($title)">
                  <http:multipart boundary="-=-=-= i Am ThE bOuNdArY =-=-=-"
                                  content-type="multipart/related">
                     <http:body content-type="application/atom+xml">
                        <atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
                           <atom:category scheme="http://schemas.google.com/g/2005#kind"
                                          term="http://schemas.google.com/docs/2007#document"
                                          label="document"/>
                           <atom:title>
                              <xsl:value-of select="$title"/>
                           </atom:title>
                        </atom:entry>
                     </http:body>
                     <xsl:copy-of select="$body"/>
                  </http:multipart>
               </xsl:when>
               <xsl:otherwise>
                  <xsl:copy-of select="$body"/>
               </xsl:otherwise>
            </xsl:choose>
         </http:request>
      </xsl:variable>
      <!-- send the request and get the response -->
      <xsl:variable name="resp" select="http:send-request($req)"/>
      <!-- does the response look ok? -->
      <xsl:if test="not(count($resp) = (1, 2))">
         <xsl:sequence select="gdata:error('GDATA004')"/>
      </xsl:if>
      <xsl:if test="exists($resp[2]) and not($resp[2] instance of document-node())">
         <xsl:sequence select="gdata:error('GDATA005', $resp[1]/http:body/@content-type)"/>
      </xsl:if>
      <xsl:if test="xs:integer($resp[1]/@status) ne 201">
         <xsl:sequence select="gdata:error('GDATA006', $resp[1]/@status, $resp[1]/@message)"/>
      </xsl:if>
      <xsl:sequence select="$resp[2]/*"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return the folder ID from a folder entry.</doc:desc>
      <doc:param name="folder">
         The folder's Atom entry.
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:folder-id" as="xs:string">
      <xsl:param name="folder" as="element(atom:entry)"/>
      <xsl:sequence select="impl:stuff-id($folder, 'folder')"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return the document ID from a document entry.</doc:desc>
      <doc:param name="doc">
         The document's Atom entry.
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:document-id" as="xs:string">
      <xsl:param name="doc" as="element(atom:entry)"/>
      <xsl:sequence select="impl:stuff-id($doc, 'document')"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return the spreadsheet ID from a spreadsheet entry.</doc:desc>
      <doc:param name="sheet">
         The spreadsheet's Atom entry.
      </doc:param>
   </doc:doc>
   <xsl:function name="gdoc:spreadsheet-id" as="xs:string">
      <xsl:param name="sheet" as="element(atom:entry)"/>
      <xsl:sequence select="impl:stuff-id($sheet, 'spreadsheet')"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return the ID from a entry.</doc:desc>
      <doc:param name="stuff">
         The Atom entry.
      </doc:param>
   </doc:doc>
   <xsl:function name="impl:stuff-id" as="xs:string">
      <xsl:param name="stuff" as="element(atom:entry)"/>
      <xsl:param name="kind"  as="xs:string"/>
      <!-- '%3A' is ':', URI encoded -->
      <xsl:variable name="prefix" select="concat($kind, '%3A')"/>
      <xsl:variable name="id" select="impl:basename($stuff/atom:id)"/>
      <xsl:if test="not(starts-with($id, $prefix))">
         <xsl:sequence select="error((), 'ERROR, TODO: use impl:error() instead!')"/>
      </xsl:if>
      <xsl:sequence select="substring($id, string-length($prefix) + 1)"/>
   </xsl:function>


   <!-- ...........................................................................................
      Utilities.
      
      - impl:basename($href)
      - impl:folder-uri($name)
   -->

   <doc:doc>
      <doc:desc>Return the basename of an href (the last step, after the
         last '/' if any.)</doc:desc>
      <doc:param name="href">
         The href.
      </doc:param>
   </doc:doc>
   <xsl:function name="impl:basename" as="xs:string">
      <xsl:param name="href" as="xs:string"/>
      <xsl:variable name="steps" select="tokenize($href, '/')"/>
      <xsl:sequence select="
          if ( exists($steps) ) then
            $steps[last()]
          else
            $href"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>Return the folder URI given its ID.</doc:desc>
      <doc:param name="id">
         The folder id.
      </doc:param>
   </doc:doc>
   <xsl:function name="impl:folder-uri" as="xs:string">
      <xsl:param name="id" as="xs:string"/>
      <xsl:variable name="base-uri" select="
          'https://docs.google.com/feeds/folders/private/full/folder%3A'"/>
      <xsl:sequence select="concat($base-uri, encode-for-uri($id))"/>
   </xsl:function>


   <!-- ...........................................................................................
      Copyright.
   -->

   <doc:doc scope="stylesheet">
      <doc:p>Copyright.</doc:p>
      <doc:pre>
Copyright (c) 2009 Florent Georges.

DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS COMMENT.

The contents of this file are subject to the Mozilla Public License
Version 1.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/.

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
the License for the specific language governing rights and limitations
under the License.

The Original Code is: all this file.

The Initial Developer of the Original Code is Florent Georges.

Contributor(s): none.
      </doc:pre>
   </doc:doc>

</xsl:stylesheet>
